package com.caiwm.chatroom.server;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * <pre>
 * ━━━━━━神兽出没━━━━━━
 * 　　　┏┓　　　┏┓
 * 　　┏┛┻━━━┛┻┓
 * 　　┃　　　　　　　┃
 * 　　┃　　　━　　　┃
 * 　　┃　┳┛　┗┳　┃
 * 　　┃　　　　　　　┃
 * 　　┃　　　┻　　　┃
 * 　　┃　　　　　　　┃
 * 　　┗━┓　　　┏━┛
 * 　　　　┃　　　┃  神兽保佑
 * 　　　　┃　　　┃  代码无bug
 * 　　　　┃　　　┗━━━┓
 * 　　　　┃　　　　　　　┣┓
 * 　　　　┃　　　　　　　┏┛
 * 　　　　┗┓┓┏━┳┓┏┛
 * 　　　　　┃┫┫　┃┫┫
 * 　　　　　┗┻┛　┗┻┛
 * ━━━━━━感觉萌萌哒━━━━━━
 * </pre>
 *
 * @author shiqla
 * @Desc 客户端线程处理类 消息由两部分组成，头部和消息体｛head:"",body:""｝
 * @Date 2019/1/10/010
 */
public class ClientExecute implements Runnable {

    private ClientSocket clientSocket;

    private String clientName;

    private List<ClientSocket> list;

    private boolean isStart = true;

    private ObjectMapper objectMapper;

    private InputStream inputStream;

    private OutputStream outputStream;

    public ClientExecute(ClientSocket clientSocket, List list) {
        this.clientSocket = clientSocket;
        this.list = list;
        objectMapper = new ObjectMapper();
        try {
            inputStream = this.clientSocket.getInputStream();
            outputStream = this.clientSocket.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void run() {
        try {
            while (isStart) {

                //最大接受10KB的数据
                byte[] bytes = new byte[10240];
                inputStream.read(bytes);

                MessageEntity messageEntity = objectMapper.readValue(bytes, MessageEntity.class);

                System.out.println("reivace : " + messageEntity.toString());

                if (messageEntity.getHead().equals(MessageType.online)) {

                    this.clientName = messageEntity.getUsername().trim();
                    this.clientSocket.setClientName(this.clientName);

                    //像已经有的客户端广播消息
                    this.sendMessage(messageEntity);

                    //像自己广播已经上线的用户信息
                    for (ClientSocket socket : list) {
                        String username = socket.getClientName();
                        MessageEntity messageEntity1 = new MessageEntity(username, MessageType.online, "");
                        this.sendMessage(messageEntity1, this.clientSocket.getSocket());
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    synchronized ("lock") {
                        this.list.add(this.clientSocket);
                    }

                } else if (messageEntity.getHead().equals(MessageType.offline)) {

                    this.isStart = false;
                    this.sendMessage(messageEntity);
                    this.close();
                    //如果是用户下线消息类型
                    synchronized ("lock") {
                        this.list.remove(this.clientSocket);
                    }
                } else if (messageEntity.getHead().equals(MessageType.privateMessage)) {
                    //如果是私信消息，则只需要给目标用户发送消息
                    String toUser = messageEntity.getToUser();
                    this.sendMessage(messageEntity, toUser);
                } else {
                    //像已经有的客户端广播消息
                    this.sendMessage(messageEntity);
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
            System.out.println(this.clientName + " 用户退出聊天室..");
            this.close();

            synchronized ("lock") {
                this.list.remove(this.clientSocket);
            }
            MessageEntity messageEntity = new MessageEntity(this.clientName, MessageType.offline, "offline");
            this.sendMessage(messageEntity);
        }
    }

    private void sendMessage(MessageEntity messageEntity, Socket socket) {
        try {
            String message = this.objectMapper.writeValueAsString(messageEntity);
            socket.getOutputStream().write(message.getBytes());
            socket.getOutputStream().flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void sendMessage(MessageEntity messageEntity, String toUser) {
        ClientSocket clientSocket = null;
        for (ClientSocket socket : list) {
            if (socket.getClientName().equals(toUser)) {
                clientSocket = socket;
                break;
            }
        }
        try {
            String message = this.objectMapper.writeValueAsString(messageEntity);
            clientSocket.getOutputStream().write(message.getBytes());
            clientSocket.getOutputStream().flush();

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private void sendMessage(MessageEntity messageEntity) {
        for (ClientSocket socket : list) {
            if (!socket.getClientName().equals(this.clientName)) {
                //所有的消息都不需要给自己的客户端发送
                try {
                    String message = this.objectMapper.writeValueAsString(messageEntity);
                    socket.getOutputStream().write(message.getBytes());
                    socket.getOutputStream().flush();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void close() {
        try {
            this.inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            this.outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try {
            this.clientSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
